import {pushTarget,popTarget} from './dep';
import {queneWatcher} from './schedular';
let id = 0;
class Watcher{
    constructor(vm,exprOrFn,callback,options){
       this.vm = vm;
       this.callback = callback;
       this.options = options;
       this.id = id++;

       this.user = options.user;//用来标识用户的状态
       this.lazy = options.lazy;
       this.dirty = this.lazy;

       this.depsId = new Set(); //记录自己都订阅过哪些Dep
       this.deps = [];

       if(typeof exprOrFn === 'function'){
         this.getter = exprOrFn;
       }else{
          //将getter方法封装成了取值函数
         this.getter = function(){
            let path = exprOrFn.split('.');
            let val = vm;
            for(let i = 0;i<path.length;i++){
               val = val[path[i]];
            }
            return val;
         }
       }
      this.value = this.lazy ? undefined: this.get(); //调用get方法，会让渲染watcher执行
    }
    addDep(dep){ //watcher不能放重复的dep dep里不能放重复的watcher
        let id = dep.id;
        if(!this.depsId.has(id)){
            this.depsId.add(id);
            this.deps.push(dep);
            dep.addSub(this);
        }
    }
    get(){
       pushTarget(this);
       let val = this.getter.call(this.vm);
       popTarget();
       return val;
    }
    update(){
    //    this.get();
      if(this.options.sync){ //同步watcher
        this.run();
      }else if(this.lazy){ //说明计算属性依赖的值发生了变化
        this.dirty = true;
      }else{
        queneWatcher(this);
      }
    }
    run(){
       let oldVal = this.value; //第一次渲染的值
       let newVal = this.get();
       this.value = newVal;

       if(this.user){ //如果是用户watcher,执行用户定义的cb
          this.callback.call(this.vm,newVal,oldVal);
       }
    }
    evaluate(){
       this.value = this.get();
       this.dirty = false;
    }
    depend(){
        let i = this.deps.length;
        while(i--){
            this.deps[i].depend();
        }
    }
    teardown(){
        let i = this.deps.length;
        while(i--){
            this.deps[i].removeSub(this);
        }
    }
}
export default Watcher
